﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Summerset.Isbndb.Books;
using System.ComponentModel;

namespace Summerset.Isbndb
{
    /// <summary>
    /// Represents an object through which requests can be issued against the ISBNdb.com API.
    /// </summary>
    public class Isbndb
    {
        #region Constructor + Methods

        /// <summary>
        /// Initializes a new instance of the <see cref="Isbndb"/> class.
        /// </summary>
        /// <param name="ApiKey">The API key.</param>
        public Isbndb(string ApiKey)
        {
            this.ApiKey = ApiKey;
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return this.Name;
        }

        #endregion
        #region Properties

        /// <summary>
        /// Gets the API key that will be used with all collection requests.
        /// </summary>
        public string ApiKey
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets or sets the page loading behavior.  By default, this is set to SyncLoadOnRequest.
        /// It is HIGHLY recommended that you leave this value at it's default.
        /// </summary>
        /// <remarks>
        /// Setting this property will not affect any previous responses returned by this object.
        /// To view the page loading behavior on these objects.
        /// NOTE: It is HIGHLY recommended that you leave this to SyncLoadOnRequest.  
        /// Certain requests can generate a HUGE number of results (ex, 'bible' generates 55,516 results as of
        /// May 2012.  That would result in this assembly attempting 5,552 requests (1 page(request) per 10)if this property 
        /// is set to either SyncLoadOnInitialization or or AsyncLoadOnInitialization.  If you are using a free api key,
        /// this would use up ALL of allowed api usage for a 24 hour period in a single request.
        /// </remarks>
        public PageLoadingBehavior PageLoadingBehavior
        {
            get
            {
                return _pageLoadingBehavior;
            }
            set
            {
                if (value != PageLoadingBehavior)                
                    _pageLoadingBehavior = value;
                
            }
        }
        PageLoadingBehavior _pageLoadingBehavior = PageLoadingBehavior.SyncLoadOnRequest;


        /// <summary>
        /// Gets or sets the name that has been assigned to this instance.  
        /// </summary>
        /// <remarks>
        /// This does not affect any behavior of this object aside from the value returned by
        /// the ToString() method, or responses from the Isbndb api.
        /// This property is simply a 'friendly name' similar to System.Threading.Thread.Name
        /// </remarks>
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                if (value != Name)                
                    _name = value;
                
            }
        }
        string _name = "Isbndb";

        #endregion
        #region Collection Request Methods

        /// <summary>
        /// Executes a request against the authors collection using the provided information.
        /// </summary>
        /// <param name="request">The information that will be used to make the reqeust.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Authors.AuthorsResponsePage, Authors.AuthorElement> ExecuteAuthorRequest(Authors.AuthorsRequest request)
        {
            return new Response<Authors.AuthorsResponsePage, Authors.AuthorElement>
                (request, this);
        }
        /// <summary>
        /// Executes a request against the authors collection using the provided information.
        /// </summary>
        /// <param name="IndexName">A valid index for the request.  <see cref="Authors.AuthorsArgs.Arguments"/> for valid indexes.</param>
        /// <param name="SearchTerms">A non-escaped string that represents the query.</param>
        /// <param name="AdditionalResultFields">Additional results to be requested from the API.  <see cref="Authors.AuthorsArgs.Results"/> for valid arguments.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Authors.AuthorsResponsePage, Authors.AuthorElement> ExecuteAuthorRequest(string IndexName, string SearchTerms, params string[] AdditionalResultFields)
        {
            return ExecuteAuthorRequest
                (new Authors.AuthorsRequest(IndexName, SearchTerms, AdditionalResultFields));
        }
        

        /// <summary>
        /// Executes a request against the books collection using the provided information.
        /// </summary>
        /// <param name="request">The information that will be used to make the reqeust.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Books.BooksResponsePage, Books.BookElement> ExecuteBookRequest(BooksRequest request)
        {
            return new Response<Books.BooksResponsePage, Books.BookElement>(request, this);
        }
        /// <summary>
        /// Executes a request against the books collection using the provided information.
        /// </summary>
        /// <param name="IndexName">A valid index for the request.  <see cref="Books.BookArgs.Arguments"/> for valid indexes.</param>
        /// <param name="SearchTerms">A non-escaped string that represents the query.</param>
        /// <param name="AdditionalResultFields">Additional results to be requested from the API.  <see cref="Books.BookArgs.Results"/> for valid arguments.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Books.BooksResponsePage, Books.BookElement> ExecuteBookRequest(string IndexName, string SearchTerms, params string[] AdditionalResultFields)
        {
            return ExecuteBookRequest(new BooksRequest(IndexName, SearchTerms, AdditionalResultFields));
        }

        
        /// <summary>
        /// Executes a request against the categories collection using the provided information.
        /// </summary>
        /// <param name="request">The information that will be used to make the reqeust.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Categories.CategoryResponsePage, Categories.CategoryElement> ExecuteCategoryRequest(Categories.CategoriesRequest request)
        {
            return new Response<Categories.CategoryResponsePage, Categories.CategoryElement>(request, this);
        }
        /// <summary>
        /// Executes a request against the categories collection using the provided information.
        /// </summary>
        /// <param name="IndexName">A valid index for the request.  <see cref="Categories.CategoriesArgs.Arguments"/> for valid indexes.</param>
        /// <param name="SearchTerms">A non-escaped string that represents the query.</param>
        /// <param name="AdditionalResultFields">Additional results to be requested from the API.  <see cref="Categories.CategoriesArgs.Results"/> for valid arguments.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Categories.CategoryResponsePage, Categories.CategoryElement> ExecuteCategoryRequest(string IndexName, string SearchTerms, params string[] AdditionalResultFields)
        {
            return ExecuteCategoryRequest(new Categories.CategoriesRequest(IndexName, SearchTerms, AdditionalResultFields));
        }
        

        /// <summary>
        /// Executes a request against the publishers collection using the provided information.
        /// </summary>
        /// <param name="request">The information that will be used to make the reqeust.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Publishers.PublisherResponsePage, Publishers.PublisherElement> ExecutePublisherRequest(Publishers.PublishersRequest request)
        {
            return new Response<Publishers.PublisherResponsePage, Publishers.PublisherElement>(request, this);
        }
        /// <summary>
        /// Executes a request against the publishers collection using the provided information.
        /// </summary>
        /// <param name="IndexName">A valid index for the request.  <see cref="Publishers.PublishersArgs.Arguments"/> for valid indexes.</param>
        /// <param name="SearchTerms">A non-escaped string that represents the query.</param>
        /// <param name="AdditionalResultFields">Additional results to be requested from the API.  <see cref="Publishers.PublishersArgs.Results"/> for valid arguments.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Publishers.PublisherResponsePage, Publishers.PublisherElement> ExecutePublisherRequest(string IndexName, string SearchTerms, params string[] AdditionalResultFields)
        {
            return ExecutePublisherRequest(new Publishers.PublishersRequest(IndexName, SearchTerms, AdditionalResultFields));
        }


        /// <summary>
        /// Executes a request against the subjects collection using the provided information.
        /// </summary>
        /// <param name="request">The information that will be used to make the reqeust.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Subjects.SubjectResponsePage, Subjects.SubjectElement> ExecuteSubjectRequest(Subjects.SubjectsRequest request)
        {
            return new Response<Subjects.SubjectResponsePage, Subjects.SubjectElement>(request, this);
        }
        /// <summary>
        /// Executes a request against the subjects collection using the provided information.
        /// </summary>
        /// <param name="IndexName">A valid index for the request.  <see cref="Subjects.SubjectArgs.Arguments"/> for valid indexes.</param>
        /// <param name="SearchTerms">A non-escaped string that represents the query.</param>
        /// <param name="AdditionalResultFields">Additional results to be requested from the API.  <see cref="Subjects.SubjectArgs.Results"/> for valid arguments.</param>
        /// <returns>A response generated by the request information.</returns>
        public Response<Subjects.SubjectResponsePage, Subjects.SubjectElement> ExecuteSubjectRequest(string IndexName, string SearchTerms, params string[] AdditionalResultFields)
        {
            return ExecuteSubjectRequest(new Subjects.SubjectsRequest(IndexName, SearchTerms, AdditionalResultFields));
        }

        #endregion
    }
}
